package com.smart.service.impl;

import com.smart.global.GlobalWord;
import com.smart.pojo.*;
import com.smart.req.ConceptualCompleteData;
import com.smart.req.LeaveCompleteData;
import com.smart.resp.LeaveBillResp;
import com.smart.resp.ReimbursementBillResp;
import com.smart.resp.UserResp;
import com.smart.service.*;
import com.smart.utils.SMUtils;
import org.activiti.engine.HistoryService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.impl.identity.Authentication;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class ConceptualProcessServiceImpl implements ConceptualProcessService {
    @Autowired
    RepositoryService repositoryService;

    @Autowired
    RuntimeService runtimeService;

    @Autowired
    TaskService taskService;

    @Autowired
    HistoryService historyService;

    @Autowired
    IConceptualProductService conceptualProductService;

    @Autowired
    IRoleService roleService;

    @Autowired
    IUserService userService;

    @Autowired
    IDepartmentService departmentService;

    @Autowired
    IProcessService processService;

    @Autowired
    ISalaryService salaryService;
    @Autowired
    IFinanceService financeService;


    @Override
    @Transactional
    public boolean startConceptualProcess(ConceptualProduct conceptualProduct) {
        //先保存研发方案,初始状态为0审批中
        conceptualProduct.setStatus(0);
        boolean save = conceptualProductService.save(conceptualProduct);

        //流程推进变量
        Map<String, Object> map = new HashMap<>();
        //设定请假申请人
        map.put("empId", conceptualProduct.getUserId());
        //设定产品部部长
        User productMinister = userService.lambdaQuery()
                .eq(User::getRoleId, GlobalWord.PRODUCT_MINISTER_ROLE_ID)
                .one();
        map.put("productMinisterId", productMinister.getId());
        //设定总经理
        User manger = userService.lambdaQuery()
                .eq(User::getRoleId, GlobalWord.MANGER_ROLE_ID)
                .one();
        map.put("mangerId", manger.getId());

        //判断是否部长申请
        User productUser = userService.getById(conceptualProduct.getUserId());
        if (productUser.getRoleId() != null) {
            //获取角色信息
            Role productRole = roleService.getById(productUser.getRoleId());
            //判断是否部长角色
            map.put("isMinister", productRole.getIsLeader() == 1);
        } else {
            //二级审批
            map.put("isMinister", false);
        }

        //构造流程实例关联请假单的唯一标识
        String businessKey = GlobalWord.DEVELOPED_KEY + "." + conceptualProduct.getId();
        //开启请假流程
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(GlobalWord.DEVELOPED_KEY, businessKey, map);
        return save & !ObjectUtils.isEmpty(processInstance);
    }

    @Override
    @Transactional
    public void complete(ConceptualCompleteData conceptualCompleteData) {
        //设置流程推进信息
        Map<String, Object> map = new HashMap<>();
        map.put("msg", conceptualCompleteData.getSequence());

        //获取当前任务节点
        Task task = taskService.createTaskQuery().taskId(conceptualCompleteData.getTaskId()).singleResult();

        //判断是否要更新研发方案信息
        if (conceptualCompleteData.getConceptualProduct() != null) {
            if (conceptualCompleteData.getConceptualProduct().getStatus() == 2) {
                conceptualCompleteData.getConceptualProduct().setStatus(0);
            } else if (task.getName().equals("总经理审批")) {
                //设置研发候选人列表
                List<Department> departmentList = departmentService.lambdaQuery().like(Department::getName, "研发").list();
                List<Long> collect = departmentList.stream().map(Department::getLeader).collect(Collectors.toList());
                String leaderString = SMUtils.listToString(collect);
                map.put("RDMinisterIds", leaderString);
                conceptualCompleteData.getConceptualProduct().setStatus(1);
            }
            conceptualProductService.updateById(conceptualCompleteData.getConceptualProduct());
        }

        //获取businessKey
        ProcessInstance pi = runtimeService.createProcessInstanceQuery()
                .processInstanceId(task.getProcessInstanceId())
                .singleResult();
        String businessKey = pi.getBusinessKey();

        //获取当前流程实例关联的研发方案
        ConceptualProduct bill = conceptualProductService.getById(Long.parseLong(businessKey.split("\\.")[1]));

        //设置批注人以及批注信息
        Authentication.setAuthenticatedUserId(conceptualCompleteData.getUserId().toString());
        taskService.addComment(task.getId(), task.getProcessInstanceId(), conceptualCompleteData.getComment());

        //如果是驳回流程,更新请假单信息
        if (conceptualCompleteData.getSequence().equals("驳回")) {
            bill.setStatus(2);
            conceptualProductService.updateById(bill);
        } else if (conceptualCompleteData.getSequence().equals("放弃研发")) {
            bill.setStatus(1);
            bill.setDeptId(null);
            conceptualProductService.updateById(bill);
        }

        //领取流程并推进
        if (task.getAssignee() == null) {
            taskService.claim(conceptualCompleteData.getTaskId(), conceptualCompleteData.getUserId().toString());
            bill.setStatus(3);
            bill.setDeptId(departmentService.lambdaQuery().eq(Department::getLeader, conceptualCompleteData.getUserId()).one().getId());
            conceptualProductService.updateById(bill);
            map.put("RDMinisterId", conceptualCompleteData.getUserId());
        }
        taskService.complete(conceptualCompleteData.getTaskId(), map);

        //判断流程是否结束
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
                .processInstanceId(task.getProcessInstanceId())
                .singleResult();

        if (processInstance == null) {
            //流程结束，处理研发成功相关信息
            bill.setStatus(4);
            conceptualProductService.updateById(bill);

            //保存研发拨款的财务记录
            Finance finance = new Finance();
            finance.setType(1);
            finance.setAmount(bill.getRdFunding());
            financeService.save(finance);

            //计算部门成员研发分红
            Department department = departmentService.getById(bill.getDeptId());
            List<UserResp> userRespList = userService.queryByDeptId(bill.getDeptId());
            //取研发资金的一成作为部门研发分红
            BigDecimal rdFunding = bill.getRdFunding().multiply(new BigDecimal("0.1"));
            if (userRespList.size() == 1) {
                UserResp leader = userRespList.get(0);
                Salary salary = salaryService.getByUserId(leader.getId());
                salary.setRdAmount(salary.getRdAmount().add(rdFunding));
                salaryService.updateById(salary);
            }
            for (UserResp userResp : userRespList) {
                Salary salary = salaryService.getByUserId(userResp.getId());
                if (userResp.getId() == department.getLeader()) {
                    salary.setRdAmount(salary.getRdAmount().add(rdFunding.multiply(new BigDecimal("0.5"))));
                } else {
                    salary.setRdAmount(salary.getRdAmount()
                            .add(rdFunding.multiply(new BigDecimal("0.5"))
                                    .divide(new BigDecimal(userRespList.size() - 1), 2, BigDecimal.ROUND_DOWN)));
                }
                salaryService.updateById(salary);
            }
        }
    }

    @Override
    public Map<String, Object> getDevelopedTask(Long userId) {
        //构建返回Map
        Map<String, Object> map = new HashMap<>();
        //查看当前用户所属部门是否领取研发方案
        Department one = departmentService.lambdaQuery().eq(Department::getLeader, userId).one();
        ConceptualProduct conceptualProduct = conceptualProductService.lambdaQuery()
                .eq(ConceptualProduct::getStatus, 3)
                .eq(ConceptualProduct::getDeptId, one.getId())
                .one();
        if (conceptualProduct != null) {
            map.put("isDeveloped", true);
            String businessKey = GlobalWord.DEVELOPED_KEY + "." + conceptualProduct.getId();
            Task task = taskService.createTaskQuery().processInstanceBusinessKey(businessKey).singleResult();
            TaskInfo taskInfo = new TaskInfo();
            taskInfo.setTaskId(task.getId());
            map.put("taskForm", processService.viewTaskForm(task.getId()));
            map.put("task", taskInfo);
        } else {
            map.put("isDeveloped", false);
            List<Task> taskList = taskService.createTaskQuery()
                    .taskName("确认研发部门")
                    .taskCandidateUser(userId.toString())
                    .list();
            List<TaskInfo> taskInfos = new ArrayList<>();
            for (Task task : taskList) {
                TaskInfo taskInfo = new TaskInfo();
                taskInfo.setTaskId(task.getId());
                taskInfo.setCreateTime(task.getCreateTime());
                String businessKey = runtimeService.createProcessInstanceQuery()
                        .processInstanceId(task.getProcessInstanceId())
                        .singleResult()
                        .getBusinessKey();
                String billId = businessKey.split("\\.")[1];
                ConceptualProduct byId = conceptualProductService.getById(billId);
                taskInfo.setName(byId.getTitle());

                taskInfos.add(taskInfo);
            }
            map.put("taskList", taskInfos);
        }
        return map;
    }
}
